home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
other
/
pmdev
/
c
/
demos
/
dynamic.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-28
|
6KB
|
225 lines
/*
*
* $VER: Dynamic.c 1.1 (05.09.98)
*
* Popup Menu example program
*
* ©1996-1998 Henrik Isaksson
* All Rights Reserved.
*
*/
#include <intuition/intuition.h>
#include <exec/memory.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <clib/alib_protos.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <libraries/pm.h>
#include <proto/pm.h>
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct PopupMenuBase *PopupMenuBase;
struct Window *w; // This window is only needed to find out when and where the menu should appear.
// The font in this window's rastport will be used for the menu.
BOOL was_called=FALSE; // Just used to find out if the destructor is called.
struct PopupMenu * __saveds __asm SubConstructFunc(register __a0 struct Hook *hook,
register __a2 struct PopupMenu *selected, register __a1 APTR *handle)
{
struct PopupMenu *newpm, *itm;
char bfr[128];
int i;
BOOL stop=FALSE;
// Don't try to open windows, requesters or print text from this
// hook, wich is called while the menu is still open.
// The display might be locked!
newpm=PM_MakeMenu(
itm=PMItem("(loading...)"), PM_ID, 300, PM_Disabled, TRUE, PMEnd,
PMEnd;
if(newpm) {
if(selected->Sub) {
// We don't have to worry about freeing the new menu,
// as it will be freed automatically. But we do have
// to take care of the old menu, since the library
// won't know it exists.
PM_FreePopupMenu(selected->Sub);
}
selected->Sub=newpm;
PM_AbortHook(*handle);
Delay(50);
PM_RemoveMenuItem(newpm, itm);
//
// We can also add items to a previously created menu
//
PM_InsertMenuItem(newpm,
PM_Insert_Last, TRUE,
PM_Insert_Item, PM_MakeItem(PM_Title, "These items have been added", TAG_DONE),
PM_Insert_Item, PM_MakeItem(PM_Title, "to the end of the menu!", TAG_DONE),
PM_Insert_Item, PM_MakeItem(PM_Title, "---------------- This item will be removed... ----------------", PM_ID, 100, TAG_DONE),
TAG_DONE);
//
// Insert before an item
// The menu must have a 'header' (an invisible item at
// the top) for this to work reliably.
//
PM_InsertMenuItem(newpm,
PM_Insert_BeforeID, 100,
PM_Insert_Item, PM_MakeItem(PM_Title, "This item has been inserted.", TAG_DONE),
TAG_DONE);
//
// Insert after an item
//
PM_InsertMenuItem(newpm,
PM_Insert_AfterID, 100,
PM_Insert_Item, PM_MakeItem(PM_Title, ",,^..^,,", TAG_DONE),
TAG_DONE);
PM_AbortHook(*handle); // update the menu and give the user a chance to see it...
Delay(50);
//
// Let's remove that long item
//
PM_RemoveMenuItem(newpm, PM_FindItem(newpm, 100));
//
// Add a few more items, and check if the user wants to abort
//
for(i=0;i<10;i++) {
Delay(10);
PM_InsertMenuItem(newpm,
PM_Insert_Last, TRUE,
PM_Insert_Item, PM_MakeItem(PM_Title, "new item", TAG_DONE),
TAG_DONE);
if(stop=PM_AbortHook(*handle)) break;
}
}
if(!stop)
return selected->Sub; // If you return NULL, no menu will be opened.
else
return NULL;
}
void __saveds __asm SubDestructFunc(register __a0 struct Hook *hook,
register __a2 struct PopupMenu *parent)
{
// Don't try to open windows, requesters or print text from this
// hook, wich is called while the menu is still open.
// The display might be locked, and input definitely is.
//
// Here you can do something with your item's userdata...
//
// parent->Sub->UserData=0;
//
// ...or free the submenu, if you want to. Otherwise it will be free'd
// when you free the rest of the menu. If you decide to free the menu,
// remember to set parent->Sub to NULL.
// (maybe it's a very large menu, and you want to return the used mem)
//
// PM_FreePopupMenu(parent->Sub);
// parent->Sub=NULL;
//
was_called=TRUE; // Only to find out if this works...
}
struct Hook SubConstruct;
struct Hook SubDestruct;
struct PopupMenu *MakeTestMenu(void);
void main()
{
struct IntuiMessage *im,imsg;
struct PopupMenu *p;
BOOL r=TRUE;
SubConstruct.h_Entry=(HOOKFUNC)SubConstructFunc;
SubConstruct.h_Data=NULL; // User Data - you can put anything you like to here.
SubDestruct.h_Entry=(HOOKFUNC)SubDestructFunc;
SubDestruct.h_Data=NULL; // User Data - you can put anything you like to here.
PopupMenuBase=(struct PopupMenuBase *)OpenLibrary(POPUPMENU_NAME,POPUPMENU_VERSION); // Open the library
if(PopupMenuBase) {
IntuitionBase=(struct IntuitionBase *)PopupMenuBase->pmb_IntuitionBase; // We let popupmenu.library open the libraries we need
GfxBase=(struct GfxBase *)PopupMenuBase->pmb_GfxBase; // They remain valid until the library is closed!
p=MakeTestMenu(); // Declared at the end of this file.
if(p) {
w=OpenWindowTags(NULL, WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_VANILLAKEY, // Open a little window
WA_RMBTrap, TRUE,
WA_DragBar, TRUE,
WA_Width, 150,
WA_Height, 100,
WA_Left, 0,
WA_Top, 100,
WA_Title, "Dynamic Menus",
WA_CloseGadget, TRUE,
TAG_DONE);
if(w) {
while(r) {
WaitPort(w->UserPort); // Wait for a message
while((im=(struct IntuiMessage *)GetMsg(w->UserPort))) { // Get the message
CopyMem(im,&imsg,sizeof(struct IntuiMessage)); // Copy the contents of it
ReplyMsg((struct Message *)im); // Reply the message
if(imsg.Class==IDCMP_MOUSEBUTTONS) {
PM_OpenPopupMenu(w,
PM_Menu, p,
TAG_DONE);
}
if(imsg.Class==IDCMP_CLOSEWINDOW) r=FALSE; // See if the user wants to quit
}
}
printf("The destructor hook was %scalled!\n", was_called?"":"NOT ");
CloseWindow(w);
} else printf("Window error!\n");
PM_FreePopupMenu(p);
} else printf("Menu error!\n");
CloseLibrary((struct Library *)PopupMenuBase);
}
}
struct PopupMenu *MakeTestMenu()
{
struct PopupMenu *p;
p=PM_MakeMenu(
PMItem("Dynamic SubMenu"),
PM_SubConstruct, &SubConstruct,
PM_SubDestruct, &SubDestruct,
PMSimpleSub,
PMInfo("This won't work unless"), End, // this will be shown if the demo doesn't work
PMInfo("you get version 7.50!"), End, // (maybe an old version of the library)
End,
End,
PMBar, End,
PMItem("Quit"), End,
End;
return p;
}